﻿//-----------------------------------------------------------------------------------------
// <copyright file="Haptics.cs" company="Jakub Florczyk (www.jakubflorczyk.pl)">
//      Copyright © 2009 Jakub Florczyk (www.jakubflorczyk.pl)
//      http://samsungmobilesdknet.codeplex.com
// </copyright>
//-----------------------------------------------------------------------------------------

namespace SamsungMobileSDKNET
{
    using System.Runtime.InteropServices;

    /// <summary>
    /// A callback function pointer type called when playing stops or completes.
    /// </summary>
    /// <param name="hapticsHandle">Haptics handle.</param>
    /// <param name="note">Haptics fundamental unit.</param>
    /// <remarks>
    /// Please refer to <see cref="M:SamsungMobileSDKNET.Haptics.PlayNotes"/> for more details on when this callback is called.
    /// </remarks>
    public delegate void HapticsFinishedPlayNotification(int hapticsHandle, out HapticsNote note);

    /// <summary>
    /// Specifies error codes specific to the Haptics API.
    /// </summary>
    public enum HapticsError
    {
        /// <summary>
        /// Invalid handle.
        /// </summary>
        InvalidHandle = ResultCode.HapticsResultBase,

        /// <summary>
        /// Out of handles.
        /// </summary>
        OutOfHandles = ResultCode.HapticsResultBase + 1,

        /// <summary>
        /// Invalid key.
        /// </summary>
        InvalidKey = ResultCode.HapticsResultBase + 2
    }

    /// <summary>
    /// The state of the haptics device.
    /// </summary>
    public enum HapticsState
    {
        /// <summary>
        /// State idle.
        /// </summary>
        Idle,

        /// <summary>
        /// State playing.
        /// </summary>
        Playing,

        /// <summary>
        /// State paused.
        /// </summary>
        Paused
    }

    /// <summary>
    /// A haptics note style determines how the curve of the playing cycle will be formed.
    /// </summary>
    public enum HapticsNoteStyle
    {
        /// <summary>
        /// A sawtooth wave, with no rising curve and a curve on the falling edge of the playing cycle.
        /// </summary>
        Strong,

        /// <summary>
        /// A round wave, with curve on the rising and falling edge of the playing cycle.
        /// </summary>
        Smooth,

        /// <summary>
        /// A square wave, with no curve on the rising or falling edge of the playing cycle.
        /// </summary>
        Sharp
    }

    /// <summary>
    /// The fundamental unit that can be played by the haptics device.   
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct HapticsNote
    {
        /// <summary>
        /// Intensity of the vibration, at its peak.
        /// </summary>
        public byte Magnitude;

        /// <summary>
        /// Starting magnitude.
        /// </summary>
        public byte StartingMagnitude;

        /// <summary>
        /// Ending magnitude.
        /// </summary>
        public byte EndingMagnitude;

        /// <summary>
        /// Total duration of haptics playing time, in milliseconds.
        /// </summary>
        public uint Duration;

        /// <summary>
        /// Start time duration, in milliseconds.
        /// </summary>
        public uint StartTimeDuration;

        /// <summary>
        /// End time duration, in milliseconds.
        /// </summary>
        public uint EndTimeDuration;

        /// <summary>
        /// Note style.
        /// </summary>
        public HapticsNoteStyle Style;

        /// <summary>
        /// Period, in milliseconds. The range is defined (minPeriod, maxPeriod) in SmiHapticsCapabilities.
        /// </summary>
        public uint Period;
    }

    /// <summary>
    /// Specifies the capabilities of the haptics device.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct HapticsCapabilities
    {
        /// <summary>
        /// Maximum period, in milliseconds.
        /// </summary>
        public uint MaxPeriod;

        /// <summary>
        /// Minimum period, in milliseconds.
        /// </summary>
        public uint MinPeriod;

        /// <summary>
        /// Start/end magnitude support. Supports start/end magnitude if value is 1, otherwise is 0.
        /// </summary>
        public bool StartEndMagIsSupported;

        /// <summary>
        /// Note style support. Supports note style if value is 1, otherwise is 0.
        /// </summary>
        public bool NoteStyleIsSupported;

        /// <summary>
        /// Periodic play support. Supports periodic play if value is 1, otherwise is 0.
        /// </summary>
        public bool PeriodicPlayIsSupported;

        /// <summary>
        /// Pause/resume support. Supports pause and resume if value is 1, otherwise is 0.
        /// </summary>
        public bool PauseResumeIsSupported;
    }

    /// <summary>
    /// Samsung Haptics API.
    /// </summary>
    /// <remarks>
    /// This haptics API allows the programmer to play haptic notes, or vibrations.
    /// <br/>
    /// The interface allows the application to play, stop, pause, and resume the playing note.
    /// <br/><br/>
    /// The haptics API also provides notification via callbacks when playing stops or ends.
    /// <br/>
    /// Play can stop or end in any of the following scenarios:    
    /// <list type="bullet">
    /// <item>All the notes specified in SmiHapticsPlayNotes() have been played.</item>
    /// <item>Play is stopped by calling SmiHapticsStop().</item>
    /// <item>A previously playing note is stopped by a subsequent call to SmiHapticsPlayNotes() with the same handle.</item>
    /// </list>
    /// </remarks>
    public class Haptics
    {        
        /// <summary>
        /// Sets the license key, if it is required. Some haptics hardware vendors require that developers purchase a license from them prior to distributing applications that use the Samsung Haptics API to access the haptics component on a Samsung phone. This provides a way for developers to provide the hardware vendor license key.
        /// <br/><br/>
        /// If such a license key is not provided, the Samsung Haptics API will display a message box when <see cref="M:SamsungMobileSDKNET.Haptics.Open"/> is called the first time after the application is started.
        /// </summary>
        /// <param name="key">A pointer to the key data. </param>
        /// <param name="count">Total byte count for the input key.</param>
        [DllImport(Common.DllName, EntryPoint = "SmiHapticsSetKey")]
        public static extern void SetKey(
            [In] byte[] key,
            [In] uint count);

        /// <summary>
        /// Opens the haptics device and returns a handle.
        /// </summary>
        /// <param name="handle">A pointer to the haptics device handle.</param>
        /// <returns>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.Success"/> on success
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorInvalidParameter"/> if the input parameter is NULL
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorDeviceNotFound"/> if a haptics device is not found
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.HapticsError.InvalidKey"/> if a valid key is required and missing
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.HapticsError.OutOfHandles"/> if out of handles
        /// </returns>
        [DllImport(Common.DllName, EntryPoint = "SmiHapticsOpen")]
        public static extern ResultCode Open(
            [Out] out int handle);

        /// <summary>
        /// Releases resources of the specified handle.
        /// </summary>
        /// <param name="handle">The haptics device handle.</param>
        [DllImport(Common.DllName, EntryPoint = "SmiHapticsClose")]
        public static extern void Close(
            [In] int handle);

        /// <summary>
        /// Gets the capabilities of the haptics device.
        /// </summary>
        /// <param name="capabilities">A pointer to the capabilities of the device.</param>
        /// <returns>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.Success"/> on success
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorInvalidParameter"/> if the input parameter is NULL 
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorDeviceNotFound"/> if a haptics device is not found 
        /// </returns>
        [DllImport(Common.DllName, EntryPoint = "SmiHapticsGetCapabilities")]
        public static extern ResultCode GetCapabilities(
            [Out] out HapticsCapabilities capabilities);

        /// <summary>
        /// Plays an array of haptics notes for the specified handle.
        /// </summary>
        /// <param name="handle">The haptics device handle.</param>
        /// <param name="noteCount">The number of haptics notes in the note array.</param>
        /// <param name="notes">The haptics note array to be played. </param>
        /// <param name="repeat">If TRUE, repeat the notes after the notes have been played. If repeat is TRUE, play never stops until <see cref="M:SamsungMobileSDKNET.Haptics.Stop"/> is called.</param>
        /// <param name="callback">The callback function called when play is completed.</param>
        /// <returns>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.Success"/> on success 
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorInvalidParameter"/> if the noteCount parameter is 0 or notes parameter is NULL
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.HapticsError.InvalidHandle"/> if the haptics handle is not valid
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorDeviceNotFound"/> if a haptics device is not found 
        /// </returns>
        /// <remarks>
        /// A handle can be used to play only one haptics note at a time; all previous notes will be stopped. When a note has finished playing, the state of its handle will be <see cref="F:SamsungMobileSDKNET.Haptics.State.Idle"/>.
        /// <br/><br/>
        /// If callback is not NULL, the callback function will be called from the haptics library thread in the following scenarios:
        /// <list type="bullet">
        /// <item>All the notes specified in <see cref="M:SamsungMobileSDKNET.Haptics.PlayNotes"/> have been played.</item>
        /// <item>Play is stopped by calling <see cref="M:SamsungMobileSDKNET.Haptics.Stop"/>.</item>
        /// <item>A previously playing note is stopped by a subsequent call to <see cref="M:SamsungMobileSDKNET.Haptics.PlayNotes"/> with the same handle.</item>
        /// <item>The haptics device is disabled by SmiHapticsDisableDevice() while a note is being played.</item>
        /// </list>
        /// <br/>
        /// It is the application's responsibility to allocate and deallocate memory associated with notes. The application must make sure the memory associated with notes is valid for the entire time the note is being played. The application can delete the note array pointer in the callback function. It is also the application's responsibility to ensure that the noteCount parameter and the actual number of notes in the notes array are equal. If an element in the notes array has an invalid style value, <see cref="F:SamsungMobileSDKNET.Haptics.NoteStyle.Smooth"/> will be used.
        /// <br/><br/>
        /// <see cref="M:SamsungMobileSDKNET.Haptics.PlayNotes"/> will make the best effort to ensure all notes can be played without any jitter between them, but it is not guaranteed.
        /// </remarks>
        [DllImport(Common.DllName, EntryPoint = "SmiHapticsPlayNotes")]
        public static extern ResultCode PlayNotes(
            [In] int handle,
            [In] uint noteCount,
            [In] HapticsNote[] notes,
            [In] bool repeat,
            [In] HapticsFinishedPlayNotification callback);

        /// <summary>
        /// Pauses the notes playing on the specified handle.
        /// </summary>
        /// <param name="handle">The haptics device handle</param>
        /// <returns>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.Success"/> on success
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.HapticsError.InvalidHandle"/> if the haptics handle is not valid
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorDeviceNotFound"/> if a haptics device is not found 
        /// </returns>
        [DllImport(Common.DllName, EntryPoint = "SmiHapticsPause")]
        public static extern ResultCode Pause(
            [In] int handle);

        /// <summary>
        /// Resumes a paused note.
        /// </summary>
        /// <param name="handle">The haptics device handle.</param>
        /// <returns>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.Success"/> on success
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.HapticsError.InvalidHandle"/> if the haptics handle is not valid
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorDeviceNotFound"/> if a haptics device is not found 
        /// </returns>
        [DllImport(Common.DllName, EntryPoint = "SmiHapticsResume")]
        public static extern ResultCode Resume(
            [In] int handle);

        /// <summary>
        /// Stops playing a note.
        /// </summary>
        /// <param name="handle">The haptics device handle.</param>
        [DllImport(Common.DllName, EntryPoint = "SmiHapticsStop")]
        public static extern void Stop(
            [In] int handle);

        /// <summary>
        /// Gets state of the specified handle.
        /// </summary>
        /// <param name="handle">The haptics device handle.</param>
        /// <param name="state">The state of the haptics device.</param>
        /// <returns>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.Success"/> on success
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorInvalidParameter"/> if the state parameter is NULL
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.HapticsError.InvalidHandle"/> if the haptics handle is not valid
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorDeviceNotFound"/> if a haptics device is not found 
        /// </returns>
        [DllImport(Common.DllName, EntryPoint = "SmiHapticsGetState")]
        public static extern ResultCode GetState(
            [In] int handle,
            [Out] out HapticsState state);               
    }
}
